package com.caseprocessing.service;

import com.caseprocessing.model.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 元数据提取器
 * 负责从案卷文档中提取各种元数据信息
 */
public class MetadataExtractor {
    
    /**
     * 提取文档完整元数据
     */
    public DocumentMetadata extractMetadata(CaseDocument caseDoc) {
        DocumentMetadata metadata = new DocumentMetadata();
        
        // 提取结构元数据
        extractStructureMetadata(caseDoc, metadata);
        
        // 提取质量元数据
        extractQualityMetadata(caseDoc, metadata);
        
        // 提取时间元数据
        extractTimeMetadata(caseDoc, metadata);
        
        // 执行完整性验证
        performCompletenessCheck(caseDoc, metadata);
        
        // 设置技术参数
        setProcessingInfo(metadata);
        
        return metadata;
    }
    
    /**
     * 提取结构元数据
     */
    private void extractStructureMetadata(CaseDocument caseDoc, DocumentMetadata metadata) {
        // 查找封面页
        Integer coverPage = findCoverPage(caseDoc);
        metadata.setCoverPage(coverPage);
        
        // 查找目录页范围
        List<Integer> directoryPages = findDirectoryPages(caseDoc);
        metadata.setDirectoryPages(directoryPages);
        
        // 查找备考表页
        Integer backupTablePage = findBackupTablePage(caseDoc);
        metadata.setBackupTablePage(backupTablePage);
        
        // 计算正文页面范围
        PageRange documentRange = calculateDocumentPageRange(caseDoc, directoryPages, backupTablePage);
        metadata.setDocumentPageRange(documentRange);
        
        // 统计文件总数（从目录中提取）
        int totalDocs = countDocumentsFromDirectory(caseDoc, directoryPages);
        metadata.setTotalDocuments(totalDocs);
    }
    
    /**
     * 查找封面页
     */
    private Integer findCoverPage(CaseDocument caseDoc) {
        for (Page page : caseDoc.getPages()) {
            String content = page.getFullText().toLowerCase();
            
            // 检查封面关键词
            if (content.contains("案卷") && (content.contains("封面") || 
                content.contains("全宗名称") || content.contains("类目名称"))) {
                return page.getPageId();
            }
        }
        return 1; // 默认第一页为封面
    }
    
    /**
     * 查找目录页范围
     */
    private List<Integer> findDirectoryPages(CaseDocument caseDoc) {
        List<Integer> directoryPages = new ArrayList<>();
        
        for (Page page : caseDoc.getPages()) {
            String content = page.getFullText();
            
            // 检查目录关键词和表格结构
            if (content.contains("卷内文件目录") || 
                (content.contains("序号") && content.contains("文号") && 
                 content.contains("责任者") && content.contains("题名"))) {
                directoryPages.add(page.getPageId());
            }
        }
        
        return directoryPages;
    }
    
    /**
     * 查找备考表页
     */
    private Integer findBackupTablePage(CaseDocument caseDoc) {
        // 从后往前查找备考表
        List<Page> pages = caseDoc.getPages();
        for (int i = pages.size() - 1; i >= 0; i--) {
            Page page = pages.get(i);
            String content = page.getFullText();
            
            if (content.contains("卷内备考表") || content.contains("本卷情况说明") || 
                content.contains("立卷人") || content.contains("检查人")) {
                return page.getPageId();
            }
        }
        
        return pages.size(); // 默认最后一页为备考表
    }
    
    /**
     * 计算正文页面范围
     */
    private PageRange calculateDocumentPageRange(CaseDocument caseDoc, 
                                               List<Integer> directoryPages, 
                                               Integer backupTablePage) {
        int startPage = 1;
        int endPage = caseDoc.getTotalPages();
        
        // 正文开始页：目录页之后
        if (!directoryPages.isEmpty()) {
            startPage = Collections.max(directoryPages) + 1;
        }
        
        // 正文结束页：备考表之前
        if (backupTablePage != null) {
            endPage = backupTablePage - 1;
        }
        
        return new PageRange(startPage, endPage);
    }
    
    /**
     * 从目录中统计文件数量
     */
    private int countDocumentsFromDirectory(CaseDocument caseDoc, List<Integer> directoryPages) {
        if (directoryPages.isEmpty()) {
            return 0;
        }
        
        int documentCount = 0;
        for (Integer pageNum : directoryPages) {
            Page page = caseDoc.getPages().get(pageNum - 1);
            String content = page.getFullText();
            
            // 简单统计：按行数估算（实际应该解析表格结构）
            String[] lines = content.split("\n");
            for (String line : lines) {
                // 如果行包含数字序号，认为是一个文件条目
                if (line.trim().matches("^\\d+\\s+.*")) {
                    documentCount++;
                }
            }
        }
        
        return documentCount;
    }
    
    /**
     * 提取质量元数据
     */
    private void extractQualityMetadata(CaseDocument caseDoc, DocumentMetadata metadata) {
        List<Page> pages = caseDoc.getPages();
        
        // 计算整体OCR置信度
        double totalConfidence = 0;
        int blockCount = 0;
        
        // 收集页面质量问题
        List<PageQualityIssue> qualityIssues = new ArrayList<>();
        
        for (Page page : pages) {
            PageMetadata pageMetadata = page.getPageMetadata();
            
            if (pageMetadata != null) {
                // 累计OCR置信度
                double pageConfidence = pageMetadata.getOcrConfidence();
                totalConfidence += pageConfidence;
                
                // 检查质量问题
                if (pageConfidence < 0.8) {
                    qualityIssues.add(new PageQualityIssue(page.getPageId(), "OCR置信度低", "中"));
                }
                
                if (pageMetadata.getImageQuality() < 0.7) {
                    qualityIssues.add(new PageQualityIssue(page.getPageId(), "图像质量差", "中"));
                }
                
                if (pageMetadata.isBlank()) {
                    qualityIssues.add(new PageQualityIssue(page.getPageId(), "空白页", "低"));
                }
            }
            
            // 统计文本块数量
            if (page.getTextBlocks() != null) {
                blockCount += page.getTextBlocks().size();
            }
        }
        
        // 设置整体置信度
        double overallConfidence = pages.isEmpty() ? 0 : totalConfidence / pages.size();
        metadata.setOverallOcrConfidence(overallConfidence);
        
        // 设置质量问题
        metadata.setPageQualityIssues(qualityIssues);
        
        // 计算平均图像质量
        double avgImageQuality = calculateAverageImageQuality(pages);
        metadata.setAverageImageQuality(avgImageQuality);
    }
    
    /**
     * 计算平均图像质量
     */
    private double calculateAverageImageQuality(List<Page> pages) {
        return pages.stream()
                .filter(page -> page.getPageMetadata() != null)
                .mapToDouble(page -> page.getPageMetadata().getImageQuality())
                .average()
                .orElse(0.0);
    }
    
    /**
     * 提取时间元数据
     */
    private void extractTimeMetadata(CaseDocument caseDoc, DocumentMetadata metadata) {
        List<String> dates = new ArrayList<>();
        
        // 从所有页面提取日期
        for (Page page : caseDoc.getPages()) {
            if (page.getTextBlocks() != null) {
                for (TextBlock block : page.getTextBlocks()) {
                    if (block.containsDate()) {
                        String date = extractDateFromText(block.getText());
                        if (date != null) {
                            dates.add(date);
                        }
                    }
                }
            }
        }
        
        // 计算时间范围
        if (!dates.isEmpty()) {
            Collections.sort(dates);
            CaseTimeRange timeRange = new CaseTimeRange();
            timeRange.setEarliestDocDate(dates.get(0));
            timeRange.setLatestDocDate(dates.get(dates.size() - 1));
            timeRange.setProcessingTime(getCurrentTimestamp());
            
            metadata.setCaseTimeRange(timeRange);
        }
    }
    
    /**
     * 从文本中提取日期（8位数字格式）
     */
    private String extractDateFromText(String text) {
        // 匹配8位数字日期 YYYYMMDD
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(\\d{8})");
        java.util.regex.Matcher matcher = pattern.matcher(text);
        
        if (matcher.find()) {
            String dateStr = matcher.group(1);
            // 简单验证日期合理性
            if (isValidDate(dateStr)) {
                return dateStr;
            }
        }
        
        return null;
    }
    
    /**
     * 验证日期格式的合理性
     */
    private boolean isValidDate(String dateStr) {
        if (dateStr.length() != 8) return false;
        
        try {
            int year = Integer.parseInt(dateStr.substring(0, 4));
            int month = Integer.parseInt(dateStr.substring(4, 6));
            int day = Integer.parseInt(dateStr.substring(6, 8));
            
            return year >= 1900 && year <= 2030 && 
                   month >= 1 && month <= 12 && 
                   day >= 1 && day <= 31;
        } catch (NumberFormatException e) {
            return false;
        }
    }
    
    /**
     * 执行完整性检查
     */
    private void performCompletenessCheck(CaseDocument caseDoc, DocumentMetadata metadata) {
        CompletenessCheck check = new CompletenessCheck();
        
        // 检查页码连续性
        check.setPageNumberContinuity(checkPageNumberContinuity(caseDoc));
        
        // 检查必备文书
        check.setRequiredDocsPresent(checkRequiredDocuments(caseDoc));
        
        // 检查目录完整性
        check.setDirectoryIntegrity(validateDirectoryIntegrity(caseDoc, metadata));
        
        // 检查缺失和重复页面
        check.setMissingPages(findMissingPages(caseDoc));
        check.setDuplicatePages(findDuplicatePages(caseDoc));
        
        metadata.setCompletenessCheck(check);
    }
    
    /**
     * 检查页码连续性
     */
    private boolean checkPageNumberContinuity(CaseDocument caseDoc) {
        List<Page> pages = caseDoc.getPages();
        
        for (int i = 0; i < pages.size(); i++) {
            if (pages.get(i).getPageId() != i + 1) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查必备文书是否存在
     */
    private List<RequiredDocCheck> checkRequiredDocuments(CaseDocument caseDoc) {
        List<RequiredDocCheck> checks = new ArrayList<>();
        
        // 检查封面
        boolean hasCover = caseDoc.getPages().stream()
                .anyMatch(page -> page.getFullText().toLowerCase().contains("封面") ||
                                page.getPageMetadata().getPageType().equals("cover"));
        checks.add(new RequiredDocCheck("封面", hasCover));
        
        // 检查目录
        boolean hasDirectory = caseDoc.getPages().stream()
                .anyMatch(page -> page.getFullText().contains("卷内文件目录"));
        checks.add(new RequiredDocCheck("目录", hasDirectory));
        
        // 检查备考表
        boolean hasBackupTable = caseDoc.getPages().stream()
                .anyMatch(page -> page.getFullText().contains("卷内备考表"));
        checks.add(new RequiredDocCheck("备考表", hasBackupTable));
        
        return checks;
    }
    
    /**
     * 验证目录完整性
     */
    private boolean validateDirectoryIntegrity(CaseDocument caseDoc, DocumentMetadata metadata) {
        List<Integer> directoryPages = metadata.getDirectoryPages();
        if (directoryPages.isEmpty()) {
            return false;
        }
        
        // 检查目录页是否连续
        for (int i = 1; i < directoryPages.size(); i++) {
            if (directoryPages.get(i) != directoryPages.get(i - 1) + 1) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 查找缺失页面
     */
    private List<Integer> findMissingPages(CaseDocument caseDoc) {
        List<Integer> missingPages = new ArrayList<>();
        List<Page> pages = caseDoc.getPages();
        
        for (int i = 1; i <= caseDoc.getTotalPages(); i++) {
            boolean found = pages.stream().anyMatch(page -> page.getPageId() == i);
            if (!found) {
                missingPages.add(i);
            }
        }
        
        return missingPages;
    }
    
    /**
     * 查找重复页面
     */
    private List<Integer> findDuplicatePages(CaseDocument caseDoc) {
        List<Integer> duplicatePages = new ArrayList<>();
        Map<Integer, Integer> pageCountMap = new HashMap<>();
        
        for (Page page : caseDoc.getPages()) {
            int pageId = page.getPageId();
            pageCountMap.put(pageId, pageCountMap.getOrDefault(pageId, 0) + 1);
        }
        
        for (Map.Entry<Integer, Integer> entry : pageCountMap.entrySet()) {
            if (entry.getValue() > 1) {
                duplicatePages.add(entry.getKey());
            }
        }
        
        return duplicatePages;
    }
    
    /**
     * 设置技术处理信息
     */
    private void setProcessingInfo(DocumentMetadata metadata) {
        ProcessingInfo info = new ProcessingInfo();
        info.setOcrEngine("Tesseract 5.3.0");
        info.setAlgorithmVersion("v2.1.0");
        info.setComplianceRuleVersion("v1.5.2");
        info.setProcessingDuration(System.currentTimeMillis());  // 实际应该记录真实耗时
        
        metadata.setProcessingInfo(info);
    }
    
    /**
     * 获取当前时间戳
     */
    private String getCurrentTimestamp() {
        return String.valueOf(System.currentTimeMillis());
    }
}